package crmdna.client.user;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.List;
import java.util.Set;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.googlecode.objectify.ObjectifyFilter;

import crmdna.client.group.Group;
import crmdna.client.group.Group.GroupProp;
import crmdna.client.user.User.Action;
import crmdna.client.user.User.ResourceType;
import crmdna.client.user.UserCore.UserProp;
import crmdna.common.APIException;
import crmdna.common.APIResponse.Status;
import crmdna.crmdna.Client;

public class UserTest {
	
	private final LocalServiceTestHelper datastoreHelper =
	        new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
	        	.setApplyAllHighRepJobPolicy());
	//local implementation / test harness implementation becomes HRD
	//only if setApplyAllHighRepJobPolicy is set. If the implementation is not HRD then
	//cross group transactions would fail (as master slave does not support it)
	    
	String client = "isha";
	GroupProp sgp;
	
    @Before
    public void setUp() {
        datastoreHelper.setUp();       
        ObjectifyFilter.complete();
        
//        Client.create(client);
//        sgp = Group.create(client, "Singapore", User.SUPER_USER);
//        assertEquals(1, sgp.groupId);        
    }

    @After
    public void tearDown() {       
    	ObjectifyFilter.complete();
        datastoreHelper.tearDown();
    }
    
    @Test
    public void createTest() {
    	
    	//client cannot be invalid
    	try {
    		User.create("isha", "sathya.t@ishafoundation.org", 1, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create(client);
    	    	    	
    	assertEquals(0, User.getAll("isha").size());
    	
    	try {
    		User.create("isha", "sathya.t@ishafoundation.org", 1, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals("group id should be valid", Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Group.create("isha", "Singapore", User.SUPER_USER); //will be allocated id 1
    	
    	//email should be valid
    	try {
    		User.create("isha", "sathya.tishafoundation.org", 1, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED, ex.statusCode);
    	}
    	
    	//cannot add null or empty string as email
    	try {
    		User.create("isha", null, 1, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED, ex.statusCode);
    	}
    	
    	try {
    		User.create("isha", "", 1, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED, ex.statusCode);
    	}
    	
    	User.create("isha", "sAThya.t@ishafoundation.org", 1, User.SUPER_USER);
    	UserProp prop = User.get("isha", "sathya.t@ishafoundation.org").toProp();
    	assertEquals("sathya.t@ishafoundation.org", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(1, prop.userId); 
    	assertEquals(1, prop.groupId);
    	
    	//cannot create the same user again
    	try {
    		User.create("isha", "sAThya.t@ishafoundation.org", 1, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_ALREADY_EXISTS, ex.statusCode);
    	}
    	
    	//next user should get id 2
    	User.create("isha", "sAThya.isha@gmail.com", 1, User.SUPER_USER);
    	prop = User.get("isha", "sathya.isha@gmail.com").toProp();
    	assertEquals("sathya.isha@gmail.com", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(2, prop.userId);
    	
    	//test privilege
    	String login = "login@login.com";
    	User.create("isha", login, 1, User.SUPER_USER);
    	try {
    		User.create("isha", "sowmya@gmail.com", 1, login);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	User.addOrDeletePrivilege("isha", login, ResourceType.USER, 0, Action.WRITE, true, User.SUPER_USER);
    	
    	User.create("isha", "sowmya@gmail.com", 1, login); //no exception
    	prop = User.get("isha", "sowmya@gmail.com").toProp();
    	assertEquals("sowmya@gmail.com", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(4, prop.userId);  //login@login.com would be 3    	    	
    }
    
    @Test
    public void getTest() {
    	
    	//client cannot be invalid
    	try {
    		User.get("isha", "sathya.t@ishafoundation.org");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	
    	//null if not existing
    	assertEquals(null, User.get("isha", "sathya.t@ishafoundation.org"));
    	
    	Group.create("isha", "Singapore", User.SUPER_USER); //will be allocated id: 1
    	
    	User.create("isha", "sAThya.t@ishafoundation.org", 1, User.SUPER_USER);
    	UserProp prop = User.get("isha", "sathya.t@ishafoundation.org").toProp();
    	assertEquals("sathya.t@ishafoundation.org", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(1, prop.userId);
    	assertEquals(1, prop.groupId);
    	
    	//add some privileges
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
    			ResourceType.GROUP, 1, Action.WRITE, true, User.SUPER_USER);
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
    			ResourceType.GROUP, 1, Action.READ, true, User.SUPER_USER);
    	prop = User.get("isha", "sathya.t@ishafoundation.org").toProp();
    	assertEquals("sathya.t@ishafoundation.org", prop.email);
    	assertEquals(2, prop.privileges.size());
    	assertEquals(UserCore.getPrivilege(ResourceType.GROUP.toString(), 1, Action.READ.toString()), 
    			prop.privileges.first());
    	assertEquals(UserCore.getPrivilege(ResourceType.GROUP.toString(), 1, Action.WRITE.toString()), 
    			prop.privileges.last());
    	assertEquals(1, prop.userId);  
    	assertEquals(1, prop.groupId);
    }
    
    @Test
    public void safeGetTest() { 
    	String user = "sathya.t@ishafoundation.org";
    	String client = "isha";
    	
    	//client cannot be invalid
    	try {
    		User.safeGet(client, user);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals("client should be valid", Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create(client);
    	
    	try {
    		User.safeGet(client, user);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals("user email should exist", Status.ERROR_INVALID_USER, ex.statusCode);
		}
    	
    	long groupId = Group.create(client, "sgp", User.SUPER_USER).groupId;
    	UserCore.create(client, user, groupId);
    	
    	assertEquals("can get by email", user, User.safeGet(client, user).toProp().email);    	    	
    }
    
    @Test
    public void getAllTest() {
    	
    	//client cannot be invalid
    	try {
    		User.get("isha", "sathya.t@ishafoundation.org");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	
    	//0 when there are no users
    	assertEquals(0, User.getAll("isha").size());
    	
    	Group.create("isha", "Singapore", User.SUPER_USER); //will be allocated id 1
    	Group.create("isha", "Malaysia/KL", User.SUPER_USER); //will be allocated id 2
    	
    	User.create("isha", "weibeng@gmail.com", 2, User.SUPER_USER);
    	User.create("isha", "sAThya.t@ishafoundation.org", 1, User.SUPER_USER);
    	User.create("isha", "Thulasidhar@gmail.com", 1, User.SUPER_USER);
    	User.create("isha", "TIna@ishafoundation.org", 1, User.SUPER_USER);    	
    	
    	List<UserProp> props = User.getAll("isha");
    	assertEquals(4, props.size());
    	
    	//should be sorted by email. ids should be allocated in same order as create
    	UserProp prop = props.get(0);
    	assertEquals("sathya.t@ishafoundation.org", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(2, prop.userId); 
    	assertEquals(1, prop.groupId);
    	
    	prop = props.get(1);
    	assertEquals("thulasidhar@gmail.com", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(3, prop.userId);
    	assertEquals(1, prop.groupId);
    	
    	prop = props.get(2);
    	assertEquals("tina@ishafoundation.org", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(4, prop.userId);
    	assertEquals(1, prop.groupId);
    	
    	prop = props.get(3);
    	assertEquals("weibeng@gmail.com", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(1, prop.userId);
    	assertEquals(2, prop.groupId);
    }
    
    @Test
    public void getAllForCenterTest() {
    	
    	//client cannot be invalid
    	try {
    		User.get("isha", "sathya.t@ishafoundation.org");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	
    	//0 when there are no users
    	assertEquals(0, User.getAll("isha").size());
    	
    	GroupProp sgp = Group.create("isha", "Singapore", User.SUPER_USER); //will be allocated id 1
    	GroupProp kl = Group.create("isha", "Malaysia/KL", User.SUPER_USER); //will be allocated id 2
    	
    	User.create("isha", "weibeng@gmail.com", 2, User.SUPER_USER);
    	User.create("isha", "sAThya.t@ishafoundation.org", 1, User.SUPER_USER);
    	User.create("isha", "Thulasidhar@gmail.com", 1, User.SUPER_USER);
    	User.create("isha", "TIna@ishafoundation.org", 1, User.SUPER_USER);
    	    	    	
    	List<UserProp> props = User.getAllForGroup("isha", sgp.groupId);
    	assertEquals(3, props.size());
    	
    	//should be sorted by email. ids should be allocated in same order as create
    	UserProp prop = props.get(0);
    	assertEquals("sathya.t@ishafoundation.org", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(2, prop.userId); 
    	assertEquals(1, prop.groupId);
    	
    	prop = props.get(1);
    	assertEquals("thulasidhar@gmail.com", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(3, prop.userId);
    	assertEquals(1, prop.groupId);
    	
    	prop = props.get(2);
    	assertEquals("tina@ishafoundation.org", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(4, prop.userId);
    	assertEquals(1, prop.groupId);
    	
    	props = User.getAllForGroup("isha", kl.groupId);
    	assertEquals(1, props.size());
    	
    	prop = props.get(0);
    	assertEquals("weibeng@gmail.com", prop.email);
    	assertEquals(0, prop.privileges.size());
    	assertEquals(1, prop.userId);
    	assertEquals(2, prop.groupId);
    }
    
    @Test
    public void updateEmailTest() {
    	
    	//client cannot be invalid
    	try {
    		User.get("isha", "sathya.t@ishafoundation.org");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	Group.create("isha", "Singapore", User.SUPER_USER); //groupId will be 1
    	
    	User.create("isha", "sathya.t@ishaFoundation.org", 1, User.SUPER_USER);
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
    			ResourceType.GROUP, 1, Action.READ, true, User.SUPER_USER);
    	User.create("isha", "shiva@gmail.com", 1, User.SUPER_USER);
    	
    	assertEquals(2, User.getAll("isha").size());
    	
    	assertEquals(1, User.get("isha", "sathya.t@ishafoundation.org").userId);
    	
    	//new email cannot be invalid
    	try {
    		User.updateEmail("isha", "sathya.t@ishafoundation.org", "sathya.ishagmail.com", 
    				User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_INCORRECTLY_SPECIFIED, ex.statusCode);
    	}
    	
    	User.updateEmail("isha", "sathya.t@ishafoundation.org", 
    			"sathya.isha@gmail.com", User.SUPER_USER);
    	
    	assertTrue(null != User.get("isha", "sathya.isha@gmail.com"));
    	assertEquals(1, User.get("isha", "sathya.isha@gmail.com").userId); //same id should be retained
    	assertEquals(1, User.get("isha", "sathya.isha@gmail.com").groupId); //group id should be retained
    	//same permissions should be retained
    	assertEquals(1, User.get("isha", "sathya.isha@gmail.com").privileges.size());
    	User.ensureAccess("isha", "sathya.isha@gmail.com", ResourceType.GROUP, 1, Action.READ);
    	
    	assertEquals(null, User.get("isha", "sathya.t@ishafoundation.org"));
    	
    	//cannot change to an existing id
    	try {
    		User.updateEmail("isha", "sathya.isha@gmail.com", "shiva@gmail.com", User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_ALREADY_EXISTS, ex.statusCode);
    	}
    	
    	//can specify the same email
    	User.updateEmail("isha", "sathya.isha@gmail.com", "sathya.isha@gmail.com", User.SUPER_USER); 
    	
    	//test privileges
    	String login = "login@login.com";
    	User.create("isha", login, 1, User.SUPER_USER);
    	try {
    		User.updateEmail("isha", "sathya.isha@gmail.com", "shiva@gmail.com", login);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	User.addOrDeletePrivilege("isha", login, ResourceType.USER, 0, Action.WRITE, true, User.SUPER_USER);
    	
    	User.updateEmail("isha", "sathya.isha@gmail.com", "sowmya@gmail.com", login); //no exception
    	UserProp prop = User.get("isha", "sowmya@gmail.com").toProp();
    	assertEquals("sowmya@gmail.com", prop.email);    	
    	assertEquals(1, prop.userId);  //same id should be retained    
    }
    
    @Test
    public void updateGroupTest() {
    	
    	//client cannot be invalid
    	try {
    		User.get("isha", "sathya.t@ishafoundation.org");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	Group.create("isha", "Singapore", User.SUPER_USER); //groupId will be 1
    	Group.create("isha", "Malaysia/KL", User.SUPER_USER); //groupId will be 2
    	assertEquals(2, Group.getAll("isha").size());
    	
    	final String email = "sathya.t@ishaFoundation.org";
    	
    	User.create("isha", email, 1, User.SUPER_USER);
    	User.addOrDeletePrivilege("isha", email, 
    			ResourceType.GROUP, 1, Action.READ, true, User.SUPER_USER);
    	
    	assertEquals(1, User.getAll("isha").size());
    	
    	assertEquals(1, User.get("isha", email).userId);
    	
    	//new group cannot be invalid
    	try {
    		User.updateGroup("isha", email, 4, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals("new group id should be valid", Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
    	}
    	
    	User.updateGroup("isha", "sathya.t@ishafoundation.org", 2, User.SUPER_USER);
    	
    	UserProp prop = User.get("isha", email).toProp();
    	assertTrue(null != prop);
    	assertEquals(2, prop.groupId);
    	//same permissions should be retained
    	assertEquals(1, prop.privileges.size());
    	User.ensureAccess("isha", email, ResourceType.GROUP, 1, Action.READ);
     	    	
    	
    	//test privileges
    	String login = "login@login.com";
    	User.create("isha", login, 1, User.SUPER_USER);
    	try {
    		User.updateGroup("isha", email, 1, login);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	User.addOrDeletePrivilege("isha", login, ResourceType.USER, 0, Action.WRITE, true, User.SUPER_USER);
    	
    	User.updateGroup("isha", email, 1, login);//no exception
    	prop = User.get("isha", email).toProp();
    	assertEquals(email.toLowerCase(), prop.email);    	
    	assertEquals(1, prop.groupId);    
    }
    
    @Test
    public void ensureAccessTest() {
    	//client cannot be invalid
    	try {
    		User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    				ResourceType.GROUP, 1, Action.READ);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	
    	try {
    		User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    				ResourceType.GROUP, 1, Action.READ);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
    	}
    	
    	Group.create("isha", "Singapore", User.SUPER_USER); //will be allocated id 1
    	
    	User.create("isha", "sathya.t@ishafoundation.org", 1, User.SUPER_USER);
    	
    	try {
    		User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    				ResourceType.GROUP, 1, Action.READ);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
    			ResourceType.GROUP, 1, Action.READ, true, User.SUPER_USER);
    	
    	User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
				ResourceType.GROUP, 1, Action.READ); //no exception
    	
    	//remove privilege
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
    			ResourceType.GROUP, 1, Action.READ, false, User.SUPER_USER);
    	
    	try {
    		User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    				ResourceType.GROUP, 1, Action.READ);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	//always true for superuser
    	User.ensureAccess("isha", User.SUPER_USER, ResourceType.USER, 0, Action.WRITE);
    	User.ensureAccess("isha", User.SUPER_USER, ResourceType.USER, 0, Action.READ);
    	User.ensureAccess("isha", User.SUPER_USER, ResourceType.GROUP, 0, Action.READ);
    	User.ensureAccess("isha", User.SUPER_USER, ResourceType.GROUP, 0, Action.WRITE);
    }
    
    @Test
    public void ensureValidUserTest() {
    	//client cannot be invalid
    	try {
    		User.ensureValidUser("isha", "sathya.t@ishafoundation.org");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	
    	try {
    		User.ensureValidUser("isha", "sathya.t@ishafoundation.org");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
    	}
    	
    	Group.create("isha", "Singapore", User.SUPER_USER); //will be allocated id 1
    	User.create("isha", "sathya.t@ishafoundation.org", 1, User.SUPER_USER);
    	User.ensureValidUser("isha", "sathya.t@ishafoundation.org"); //no exception    
    	
    	//always true for superuser
    	User.ensureValidUser("isha", User.SUPER_USER);
    }
    
    @Test
    public void addOrDeletePrivilegeTest() {
    	//client cannot be invalid
    	try {
    		User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
    				ResourceType.GROUP, 1, Action.READ, true, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	
    	//user cannot be invalid
    	try {
    		User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
    				ResourceType.GROUP, 1, Action.WRITE, true, User.SUPER_USER);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
    	}
    	
    	Group.create("isha", "Singapore", User.SUPER_USER); //will be allocated id 1
    	User.create("isha", "sathya.t@ishafoundation.org", 1, User.SUPER_USER);
    	
    	//add privilege and ensureAccess
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
				ResourceType.GROUP, 1, Action.WRITE, true, User.SUPER_USER);    	
    	User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    			ResourceType.GROUP, 1, Action.WRITE);
    	
    	//should be able to add privilege again
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
				ResourceType.GROUP, 1, Action.WRITE, true, User.SUPER_USER);    	
    	User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    			ResourceType.GROUP, 1, Action.WRITE);
    	
    	//remove privilege
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
				ResourceType.GROUP, 1, Action.WRITE, false, User.SUPER_USER);
    	try {
    		User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    				ResourceType.GROUP, 1, Action.READ);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	//should be able to remove again without exception
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
				ResourceType.GROUP, 1, Action.WRITE, false, User.SUPER_USER);
    	try {
    		User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    				ResourceType.GROUP, 1, Action.READ);
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	//test privileges
    	String login = "login@gmail.com";
    	try {
	    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
					ResourceType.GROUP, 2, Action.WRITE, true, login);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INVALID_USER, ex.statusCode);
    	}
    	
    	User.create("isha", login, 1, User.SUPER_USER);
    	try {
	    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
					ResourceType.GROUP, 2, Action.WRITE, true, login);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	//give required permission to login
    	User.addOrDeletePrivilege("isha", login, ResourceType.USER, 0, 
    			Action.WRITE, true, User.SUPER_USER);
    	
    	User.addOrDeletePrivilege("isha", "sathya.t@ishafoundation.org", 
				ResourceType.GROUP, 2, Action.WRITE, true, login); //no exception
    	User.ensureAccess("isha", "sathya.t@ishafoundation.org", 
    			ResourceType.GROUP, 2, Action.WRITE);    	    	
    }
    
    @Test public void getResourcesTest() {
    	String email = "sathya.t@ishafoundation.org";  
    	
    	String client = "isha";
    	Client.create(client);
    	GroupProp sgp = Group.create(client, "Singapore", User.SUPER_USER);
        assertEquals(1, sgp.groupId);
        
    	User.create(client, email, 1, User.SUPER_USER);
    	User.addOrDeletePrivilege(client, email, ResourceType.GROUP, 1,    			
    			Action.WRITE, true, User.SUPER_USER);
    	User.addOrDeletePrivilege(client, email, ResourceType.GROUP, 2, 
    			Action.WRITE, true, User.SUPER_USER);
    	
    	Set<Long> resources = User.getResources(client, email, ResourceType.GROUP, Action.WRITE);
    	assertEquals(2, resources.size());
    	assertTrue(resources.contains((long)1));
    	assertTrue(resources.contains((long)2));
    	
    	resources = User.getResources(client, email, ResourceType.GROUP, Action.READ);
    	assertEquals(0, resources.size());
    }
    
    @Test
    public void clonePrivilegesTest() {
    	final String login = "login@login.com";
    	final String sourceEmail = "source@gmail.com";
    	final String targetEmail = "target@gmail.com";
    	
    	//client cannot be invalid
    	try {
    		User.clonePrivileges("isha", sourceEmail, targetEmail, login);    				
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	Group.create("isha", "Singapore", User.SUPER_USER); //will be allocated id 1
    	User.create("isha", login, 1, User.SUPER_USER);
    	
    	//should have correct privilege
    	try {
    		User.clonePrivileges("isha", sourceEmail, targetEmail, login);    				
    		assertTrue(false);
    	} catch (APIException ex) {   
    		assertEquals(Status.ERROR_INSUFFICIENT_PERMISSION, ex.statusCode);
    	}
    	
    	User.addOrDeletePrivilege("isha", login, ResourceType.USER, 0, Action.WRITE, true, User.SUPER_USER);
    	
    	try {
    		User.clonePrivileges("isha", sourceEmail, targetEmail, User.SUPER_USER);    				
    		assertTrue(false);
    	} catch (APIException ex) {   
    		assertEquals("source email and target email should be valid users", 
    				Status.ERROR_INVALID_USER, ex.statusCode);    		
    	}    	
    	
    	User.create("isha", sourceEmail, 1, User.SUPER_USER); //id: 2
    	User.create("isha", targetEmail, 1, User.SUPER_USER); //id: 3
    	User.addOrDeletePrivilege("isha", targetEmail, ResourceType.GROUP, 1,
    			Action.READ, true, User.SUPER_USER);
    	User.addOrDeletePrivilege("isha", targetEmail, ResourceType.GROUP, 2,
    			Action.WRITE, true, User.SUPER_USER);
    	
    	User.clonePrivileges("isha", sourceEmail, targetEmail, login);
    	crmdna.client.user.UserCore.UserProp prop = User.get("isha", sourceEmail).toProp();
    	assertEquals(2, prop.userId);
    	assertEquals(0, prop.privileges.size());
    	prop = User.get("isha", targetEmail).toProp();
    	assertEquals(3, prop.userId);
    	assertEquals(0, prop.privileges.size());
    	
    	//add some privileges to source
    	User.addOrDeletePrivilege("isha", sourceEmail, ResourceType.GROUP, 1,
    			Action.READ, true, User.SUPER_USER);
    	User.addOrDeletePrivilege("isha", sourceEmail, ResourceType.GROUP, 2,
    			Action.WRITE, true, User.SUPER_USER);
    	
    	User.clonePrivileges("isha", sourceEmail, targetEmail, login);
    	prop = User.get("isha", sourceEmail).toProp();
    	assertEquals(2, prop.userId);
    	assertEquals(2, prop.privileges.size());
    	assertEquals(1, prop.groupId);
    	
    	prop = User.get("isha", targetEmail).toProp();
    	assertEquals(3, prop.userId);
    	assertEquals(2, prop.privileges.size());
    	assertEquals(1, prop.groupId);
    	assertTrue(prop.privileges.contains(UserCore.getPrivilege(ResourceType.GROUP.toString(), 
    			1, Action.READ.toString())));
    	assertTrue(prop.privileges.contains(UserCore.getPrivilege(ResourceType.GROUP.toString(), 
    			2, Action.WRITE.toString())));    	    	    	    	    	    	  
    }
}